<?php
/**
 * raingad IM [ThinkPHP6]
 * @author xiekunyu <raingad@foxmail.com>
 */

namespace app\enterprise\model;

use app\BaseModel;
use app\shop\common\consts\Consts;
use app\shop\common\consts\RedisKey;
use app\shop\model\chat\GroupUserModel;
use app\shop\model\config\SensitiveWordModel;
use app\shop\model\file\FileModel;
use app\shop\model\order\OrderModel;
use app\shop\model\user\AdminRoleModel;
use app\shop\model\user\ChatUserModel;
use app\shop\model\user\MessageModel;
use app\shop\model\user\UserModel;
use app\shop\service\chat\ChatGroupUserService;
use app\shop\service\chat\ChatService;
use app\shop\service\chat\ChatUserService;
use app\shop\service\chat\ChatVoiceService;
use app\shop\service\config\ConfigService;
use app\shop\service\until\FileService;
use app\shop\service\user\DauService;
use GatewayClient\Gateway;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Log;
use think\facade\Queue;

class Message extends BaseModel
{
    protected $pk = "msg_id";
    protected $json = ["extends", "trans_msg"];
    protected $jsonAssoc = true;
    protected static $fileType = ['file', 'image', 'video', 'voice', 'emoticon'];

    // 添加聊天记录
    public static function addData($data)
    {
        return Db::name('message')->insert($data);
    }

    // 更新消息状态
    public static function editData($update, $map)
    {
        return Db::name('message')->where($map)->update($update);
    }

    // 查询聊天记录
    public static function getList($map, $where, $sort, $listRows, $pageSize)
    {
        $list = Db::name('message')
            ->where($map)
            ->where($where)
            ->order($sort)
            ->paginate(['list_rows' => $listRows, 'page' => $pageSize]);
        return $list;
    }

    // 查询聊天记录
    public static function getRecord($map, $sort, $listRows, $pageSize)
    {
        $list = MessageModel::where($map)
            ->order($sort)
            ->paginate(['list_rows' => $listRows, 'page' => $pageSize])
            ->toArray();
        return $list;
    }

    // 创建消息体
    public static function createMessageData($fromUid, $toUid, $type, $content)
    {
        $fromUserInfo = UserModel::find($fromUid);
        $msgInfo['id'] = \utils\Str::getUuid();
        $msgInfo['status'] = 'successd';
        $msgInfo['user_id'] = $fromUid;
        $msgInfo['sendTime'] = time() * 1000;
        $msgInfo['toContactId'] = $toUid;
        $msgInfo['type'] = $type;
        $msgInfo['content'] = str_encipher($content, false);
        $msgInfo['fromUser'] = [
            'id' => $fromUserInfo['user_id'],
            'avatar' => $fromUserInfo['avatar'],
            'displayName' => $fromUserInfo['realname']
        ];
        return $msgInfo;
    }

    /**
     * 发送消息
     * @param $param
     * @return array
     * @throws \Exception
     */
    public static function sendMessage($param)
    {
        try {
            $fromUserId = $param['user_id'];
            $chatSign = $param['chat_sign'] ?? 0;
            if (!$chatSign) {
                throw new \Exception('缺少聊天标识');
            }
            $fileId = $param['file_id'] ?? 0;
            $content = $param['content'] ?? '';
            if ($content == '') {
                throw new \Exception('不能发送空消息');
            }
            $msgType = $param['type'] ?? '';
            $id = $param['id'] ?? '';
            $quote = $param['quote'] ?? '';
            $extends = $param['extends'] ?? [];
            $transMsg = $param['trans_msg'] ?? [];
            $ossUrl = getDiskUrl();
            // 发送者信息
            $fromUserInfo = UserModel::field('user_id,mobile,realname,role_id,avatar')->find($fromUserId);
            if (!$fromUserInfo) {
                throw new \Exception('发送者不存在');
            }

            $chatSignArr = explode('-', $chatSign);
            $toContactId = $fromUserId == $chatSignArr[0] ? $chatSignArr[1] : $chatSignArr[0];
            $orderId = $chatSignArr[2];
            // 发送对象信息
            $chatInfo = ChatUserModel::where('chat_sign', $chatSign)->find();
            if (!$chatInfo) {
                // 接受者信息
                $toContactInfo = UserModel::find($toContactId);
                if ($toContactInfo && in_array($toContactInfo['role_id'], [2, 3, 5, 6])) {
                    // 建立群聊
                    $chatInfo = new ChatUserModel();
                    $chatInfo->chat_sign = $chatSign;
                    $chatInfo->order_id = $orderId;
                    $chatInfo->title = $toContactInfo['realname'];
                    $chatInfo->order_name = $fromUserInfo['realname'];
                    $chatInfo->save();

                    $groupUser = new GroupUserModel();
                    $dataAll = [
                        [
                            'chat_sign' => $chatSign,
                            'user_id' => $fromUserId
                        ],
                        [
                            'chat_sign' => $chatSign,
                            'user_id' => $toContactId
                        ],
                    ];
                    $groupUser->saveAll($dataAll);
                    // 群聊
                    $groupAvatar = (new ChatGroupUserService())->createGroupAvatar($chatSign);
                    if ($groupAvatar) {
                        ChatUserModel::update(['avatar' => $groupAvatar], ['chat_sign' => $chatSign]);
                    }

                    // 用户加入到群聊
                    Gateway::$registerAddress = config('gateway.registerAddress');
                    $fromUserClientIds = Gateway::getClientIdByUid($fromUserId);
                    foreach ($fromUserClientIds as $fromUserClientId) {
                        Gateway::joinGroup($fromUserClientId, $chatSign);
                    }
                    $toUserClientIds = Gateway::getClientIdByUid($toContactId);
                    foreach ($toUserClientIds as $toUserClientId) {
                        Gateway::joinGroup($toUserClientId, $chatSign);
                    }
                } else {
                    throw new \Exception('聊天对象错误');
                }
            } else {
                $chatUserArr = GroupUserModel::where('chat_sign', $chatSign)->column('user_id');
                if (!in_array($fromUserId, $chatUserArr)) {
                    throw new \Exception('您已不在群聊');
                }
            }
            // 检测是否在群聊中  不在则加入
            $chatUserService = new ChatUserService();
            $chatUserService->checkUserIsInGroup($fromUserId, $chatSign);

            // 更新群最后一次聊天时间
            $chatInfo->last_time = time();
            $chatInfo->save();
            // 限制发送频率
//            $config = ConfigService::getConfigValue('sysInfo');
//            if ($config['chat_interval'] > 0) {
//                $lastInfo = MessageModel::where('from_user', $fromUserId)
//                    ->where('chat_sign', $chatSign)
//                    ->where('is_undo', 0)
//                    ->where('status', 1)
//                    ->find();
//                if ($lastInfo && time() - strtotime($lastInfo['create_time']) < $config['chat_interval']) {
//                    throw new \Exception('发送频繁！至少间隔' . $config['chat_interval'] . '秒');
//                }
//            }

            // 如果是转发图片文件的消息，必须把域名去除掉
            if (in_array($msgType, self::$fileType)) {
                if (strpos($content, $ossUrl) !== false) {
                    $content = str_replace($ossUrl, '', $content);
                }
            }


            $data = ChatService::getMessageData($chatSign, $fromUserInfo, $content, $msgType, $id, $fileId, $quote, $extends, $orderId);
            $message = new self();
            $data['trans_msg'] = $transMsg;
            $message->save($data);
            $msgId = $message->msg_id;

            // 最后一条消息写入redis
            $chatVoiceService = new ChatVoiceService();
            $chatVoiceService->setLastMessageToRedis($chatSign, $msgId, $content, $msgType, $fromUserId);

            // 群组的每个人未读消息加1
            $where = [];
            $where[] = ['chat_sign', '=', $chatSign];
            $where[] = ['user_id', '<>', $fromUserId];
            GroupUserModel::update(['unread' => Db::raw("unread+1")], $where);
            // 设置日活用户
            if ($fromUserInfo['role_id'] == Consts::CUSTOMER_ID) {
                DauService::setDauData($fromUserId);
            }
            // 拼接消息推送
            $sendData = ChatService::getSendData($chatSign, $fromUserInfo, $content, $msgType, $fileId, $orderId, $id);
            if ($fileId) {
                $sendData['content'] = FileService::getFullUrl($sendData['content']);
            }

            $sendData['orderId'] = $orderId;
            $sendData['ids'] = $sendData['id'];
            $sendData['sensitive_word_id'] = 0;
            $sendData['quote'] = $quote ?: new \stdClass();
            $sendData['extends'] = $extends;
            $sendData['msg_id'] = $msgId;
            $sendData['trans_msg'] = $transMsg;
            $sendData['title'] = $chatInfo['title'];
            $sendData['avatar'] = FileService::getFullUrl($chatInfo['avatar']);
            $sendData['order_name'] = $orderId ? OrderModel::where('id', $orderId)->value('order_name', '') : '';
            $ext = '';
            if (in_array($msgType, self::$fileType)) {
                if ($msgType == 'file') {
                    $content = FileService::getFullUrlById($fileId);
                } else {
                    $content = getFileUrl($content);
                }
                $ext = getExtUrl($content);
            }
            $sendData['extUrl'] = $ext;
            // 向发送方发送消息 如果没有触发敏感词
            wsSendMsg($chatSign, 'simple', $sendData, 1);
            // 用户设置了忙碌 自动回复
//            $toUserInfo = UserModel::field('login_status')->where('user_id', $toContactId)->find();
//            if ($toUserInfo['login_status'] == 2) {
//                $jobHandlerClassName = 'app\job\OrderJob';
//                $jobQueueName = "orderJobQueue";
//                $orderData = ['id' => uniqid(), 'time' => time(), 'from_user' => $fromUserId,  'order_id' => $orderId];
//                Queue::later(2, $jobHandlerClassName, $orderData, $jobQueueName);
//            }
            return $sendData;
        } catch (\Exception $exception) {
            throw new \Exception($exception->getFile() . $exception->getLine() . $exception->getMessage());
        }
    }

    // 群禁言
    public static function nospeak($group_id, $user_id)
    {
        $group = Group::find($group_id);
        if ($group->owner_id == $user_id) {
            return true;
        }
        if ($group->setting) {
            $setting = json_decode($group->setting, true);
            $nospeak = isset($setting['nospeak']) ? $setting['nospeak'] : 0;
            $role = GroupUser::where(['group_id' => $group_id, 'user_id' => $user_id])->value('role');
            if ($nospeak == 1 && $role > 2) {
                return false;
            } elseif ($nospeak == 2 && $role != 1) {
                return false;
            }
        }
        return true;
    }

    // 将消息中的@用户加入到atListQueue中
    public static function setAtread($messages, $user_id)
    {
        foreach ($messages as $k => $v) {
            if (!isset($v['at'])) {
                continue;
            }
            if ($v['at'] && in_array($user_id, $v['at'])) {
                $atListQueue = Cache::get("atListQueue");
                $atListQueue[$v['msg_id']][] = $user_id;
                Cache::set("atListQueue", $atListQueue);
            }
        }
    }

}